package com.shioirikukuri.service.impl;

import com.shioirikukuri.dto.ComboDTO;
import com.shioirikukuri.dto.ComboItemDTO;
import com.shioirikukuri.entity.Combo;
import com.shioirikukuri.entity.Food;
import com.shioirikukuri.mapper.ComboMapper;
import com.shioirikukuri.service.IComboService;
import com.shioirikukuri.service.IFoodService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional
public class ComboServiceImpl implements IComboService {

	@Autowired
	private ComboMapper comboMapper;

	@Autowired
	private IFoodService foodService;

	@Override
	public List<ComboDTO> getAllCombos() {
		// 1. 查询所有套餐信息
		List<Combo> combos = comboMapper.findAll();

		// 2. 将实体类转换为 DTO
		return combos.stream()
				.map(combo -> {
					ComboDTO comboDTO = new ComboDTO();
					BeanUtils.copyProperties(combo, comboDTO);

					// 3. 查询套餐内包含的菜品信息
					List<Combo.ComboItem> comboItems = comboMapper.findComboItemsByComboId(combo.getId());
					List<ComboItemDTO> comboItemDTOs = comboItems.stream()
							.map(item -> {
								ComboItemDTO comboItemDTO = new ComboItemDTO();
								BeanUtils.copyProperties(item, comboItemDTO);

								// 4. 查询菜品名称
								Food food = foodService.getFoodById(item.getFoodId())
										.orElseThrow(() -> new IllegalArgumentException("菜品不存在: " + item.getFoodId()));
								comboItemDTO.setFoodName(food.getName());

								return comboItemDTO;
							})
							.collect(Collectors.toList());

					comboDTO.setComboItems(comboItemDTOs);
					return comboDTO;
				})
				.collect(Collectors.toList());
	}

	/**
	 * 根据ID获取套餐信息
	 *
	 * @param id 套餐ID
	 * @return 套餐信息（如果存在）
	 */
	@Override
	public Optional<Combo> getComboById(Long id) {
		return Optional.ofNullable(comboMapper.findById(id));
	}

	/**
	 * 保存套餐信息
	 *
	 * @param combo 套餐信息
	 * @return 插入的记录数
	 */
	@Override
	public Integer saveCombo(Combo combo) {
		// 1. 保存套餐基础信息
		int result = comboMapper.insert(combo);

		// 2. 处理关联菜品信息
		if (combo.getComboItems() != null && !combo.getComboItems().isEmpty()) {
			processComboItems(combo.getId(), combo.getComboItems());
		}
		return result;
	}



	/**
	 * 更新套餐信息（全量更新）
	 *
	 * @param id         目标套餐ID
	 * @param comboDTO   新的套餐数据
	 * @return 更新后的套餐DTO
	 * @throws IllegalArgumentException 如果菜品不存在
	 */
	@Override
	public ComboDTO updateCombo(Long id, ComboDTO comboDTO) {
		// 1. 更新套餐基础信息
		Combo existing = comboMapper.findById(id);
		if (existing == null) {
			throw new IllegalArgumentException("套餐不存在: " + id);
		}

		// 更新字段（排除 id 和 comboItems）
		BeanUtils.copyProperties(comboDTO, existing, "id", "comboItems");
		existing.setUpdatedAt(LocalDateTime.now());
		comboMapper.update(existing);

		// 2. 删除旧的关联菜品记录
		comboMapper.deleteComboItemsByComboId(id);

		// 3. 插入新的关联菜品记录
		if (comboDTO.getComboItems() != null && !comboDTO.getComboItems().isEmpty()) {
			validateFoodExistence(comboDTO.getComboItems()); // 验证菜品存在性
			saveComboItems(id, comboDTO.getComboItems()); // 保存关联菜品信息
		}

		// 4. 返回更新后的套餐DTO
		return getComboDTOById(id);
	}

	/**
	 * 处理套餐与菜品的关联信息
	 *
	 * @param comboId 套餐ID
	 * @param items   套餐内包含的菜品及其数量
	 */
	private void processComboItems(Long comboId, List<Combo.ComboItem> items) {
		// 2. 转换存储结构
		List<ComboItemDTO> saveList = items.stream()
				.map(item -> {
					Food food = foodService.getFoodById(item.getFoodId())
							.orElseThrow(() -> new IllegalArgumentException("菜品不存在: " + item.getFoodId()));
					return new ComboItemDTO(
							comboId,
							item.getFoodId(),
							item.getQuantity(),
							food.getName()
					);
				})
				.collect(Collectors.toList());

		// 3. 批量插入关联菜品信息
		comboMapper.batchInsertComboItems(comboId, saveList);
	}

	/**
	 * 验证菜品是否存在
	 *
	 * @param comboItems 套餐内包含的菜品及其数量
	 * @throws IllegalArgumentException 如果菜品不存在
	 */
	private void validateFoodExistence(List<ComboItemDTO> comboItems) {
		Set<Long> foodIds = comboItems.stream()
				.map(ComboItemDTO::getFoodId)
				.collect(Collectors.toSet());

		List<Food> existingFoods = foodService.getFoodsByIds(foodIds);
		if (existingFoods.size() != foodIds.size()) {
			Set<Long> missingIds = foodIds.stream()
					.filter(id -> existingFoods.stream().noneMatch(f -> f.getId().equals(id)))
					.collect(Collectors.toSet());

			throw new IllegalArgumentException("无效菜品ID: " + missingIds);
		}
	}

	/**
	 * 删除套餐信息
	 *
	 * @param id 套餐ID
	 */
	@Override
	public void deleteCombo(Long id) {
		// 1. 删除套餐与菜品的关联记录
		comboMapper.deleteComboItemsByComboId(id);

		// 2. 删除套餐记录
		comboMapper.deleteById(id);
	}

	/**
	 * 根据套餐ID获取套餐内包含的菜品信息
	 *
	 * @param comboId 套餐ID
	 * @return 套餐内包含的菜品信息
	 */
	@Override
	public List<Combo.ComboItem> getComboItemsByComboId(Long comboId) {
		return comboMapper.findComboItemsByComboId(comboId);
	}


	/**
	 * 创建新套餐
	 *
	 * @param comboDTO 包含套餐详细信息的DTO
	 * @return 新创建的套餐DTO
	 * @throws IllegalArgumentException 如果菜品不存在
	 */
	public ComboDTO createCombo(ComboDTO comboDTO) {
		// 1. 插入套餐基础信息
		Combo combo = new Combo();
		BeanUtils.copyProperties(comboDTO, combo, "id", "comboItems");
		comboMapper.insert(combo);

		// 2. 获取生成的套餐ID
		Long comboId = combo.getId();

		// 3. 处理套餐与菜品的关联信息
		if (comboDTO.getComboItems() != null && !comboDTO.getComboItems().isEmpty()) {
			List<ComboItemDTO> comboItems = comboDTO.getComboItems();
			validateFoodExistence(comboItems); // 验证菜品存在性
			saveComboItems(comboId, comboItems); // 保存关联菜品信息
		}

		// 4. 返回新创建的套餐DTO
		return getComboDTOById(comboId);
	}

	/**
	 * 保存套餐与菜品的关联信息
	 *
	 * @param comboId    套餐ID
	 * @param comboItems 套餐内包含的菜品及其数量
	 */
	private void saveComboItems(Long comboId, List<ComboItemDTO> comboItems) {
		List<ComboItemDTO> saveList = comboItems.stream()
				.map(item -> new ComboItemDTO(comboId, item.getFoodId(), item.getQuantity(), item.getFoodName()))
				.collect(Collectors.toList());
		comboMapper.batchInsertComboItems(comboId, saveList);
	}


	/**
	 * 根据ID获取套餐DTO
	 *
	 * @param comboId 套餐ID
	 * @return 套餐DTO
	 */
	private ComboDTO getComboDTOById(Long comboId) {
		Combo combo = comboMapper.findById(comboId);
		ComboDTO comboDTO = new ComboDTO();
		BeanUtils.copyProperties(combo, comboDTO);

		// 查询套餐内包含的菜品信息
		List<ComboItemDTO> comboItems = comboMapper.findComboItemsByComboId(comboId)
				.stream()
				.map(item -> {
					Food food = foodService.getFoodById(item.getFoodId())
							.orElseThrow(() -> new IllegalArgumentException("菜品不存在: " + item.getFoodId()));
					return new ComboItemDTO(
							comboId,
							item.getFoodId(),
							item.getQuantity(),
							food.getName()
					);
				})
				.collect(Collectors.toList());

		comboDTO.setComboItems(comboItems);
		return comboDTO;
	}


}